#include "httprequest.h"

#include <utility>
#include <algorithm>

#include "httpstate.h"

using namespace tiny_muduo;
using tiny_muduo::Method;
using tiny_muduo::HttpRequestParseState;

HttpRequest::HttpRequest(){}
HttpRequest::~HttpRequest(){}

bool HttpRequest::ParseRequestMethod(const char* start,const char* end){
//分析HTTP请求中的method，如果属于下面方法中的一种，设置属性method_,否则认为没有方法
    string method(start,end);
    bool has_method=true;
    if(method=="GET"){
        method_=kGet;
    }else if(method=="POST"){
        method_=kPost;
    }else if(method=="PUT"){
        method_=kPut;
    }else if(method=="DELETE"){
        method_=kDelete;
    }else if(method=="TRACE"){
        method_=kTrace;
    }else if(method=="OPTIONS"){
        method_=kOptions;
    }else if(method=="CONNECT"){
        method_=kConnect;
    }else if(method=="PATCH"){
        method_=kPatch;
    }else{
        has_method=false;
    }
    return has_method;
}

void HttpRequest::ParseRequestLine(const char* start,const char* end,HttpRequestParseState& state){
/*
    ParseRequestLine即解析请求行，要解析请求行，首先我们要了解http请求行的结构，一般请求行的结构像下面这样
    GET  /index.html?key1=value1&key2=value2  HTTP/1.1
    "/index.html" 是路径部分，而 "key1=value1&key2=value2" 是查询参数部分，由 "?" 进行区分。
    所以我们解析的时候，先找第一个空格，第一个空格之前的内容就是请求方法。 随后找第二个空格，两个空格之间的内容由？隔开，分别表示
    路径和请求参数 剩下的部分为http版本，我们要给版本赋予正确的值
    如果这个过程中有任何一个查找出错就会返回kParseErrno错误信息
*/
    {
        const char* space =std::find(start,end,' ');//找第一个空格
        if(space==end){
            state=kParseErrno;
            return;
        }

        if(!ParseRequestMethod(start,space)){
            state=kParseErrno;
            return;
        }
        start=space+1;
    }
    {
        const char* space=std::find(start,end,' ');
        if(space==end){
            state=kParseErrno;
            return;
        }

        const char*query=std::find(start,end,'?');
        if(query!=end){
            path_=std::move(string(start,query));
            query_=std::move(string(query+1,space));
        }else{
            path_=std::move(string(start,space));
        }
        start=space+1;
    }

    {
        const int httplen=sizeof(http)/sizeof(char)-1; //http是字符串"HTTP/"
        const char* httpindex=std::search(start,end,http,http+httplen); //http,http+httplen也就是http这个字符串，即在start，end内查找子串
        if(httpindex==end){
            state=kParseErrno;
            return;
        }

        const char chr=*(httpindex+httplen);
        if(httpindex+httplen+1==end&&(chr=='1'||chr=='0')){
            if(chr=='1'){
                version_=kHttp11;
            }else{
                version_=kHttp10;
            }
        }else{
            state=kParseErrno;
            return;
        }
    }
    state=kParseHeaders;
}

void HttpRequest::ParseBody(const char* start,const char* end,HttpRequestParseState& state){}

void HttpRequest::ParseHeaders(const char* start,const char* end,HttpRequestParseState& state){
//头部信息用 XX:XX 标识，我们找冒号，然后把两边信息用map存放起来
    if(start==end&&*start=='\r'&&*(start+1)=='\n'){
        state=kParseGotCompleteRequest;
        return;
    }

    const char* colon=std::find(start,end,':'); //colon即冒号
    if(colon==end){
        state=kParseErrno;
        return;
    }

    const char* valid=colon+1;
    while(*(valid++)!=' '){}
    headers_[std::move(string(start,colon))]=std::move(string(colon+1,valid));
    return;
}